//==================================================================
//  Copyright (C) 2006-2007  Davide Pasca
//
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Lesser General Public
//  License as published by the Free Software Foundation; either
//  version 2.1 of the License, or (at your option) any later version.
//
//  This library is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//  Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with this library; if not, write to the Free Software
//  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
//==================================================================
///
///
///
///
//==================================================================

#ifndef SPRITES_H
#define SPRITES_H

#include "psys.h"
#include "psys_stdgfx.h"
#include "image_base.h"
#include "texture_base.h"

//==================================================================
namespace GXY {

//==================================================================
//#define SLIST_BUILD_FLG_FIT	1

//==================================================================
namespace SPRITE
{
	enum TextureFlag
	{
		TEXFLG_UNUSED = -1,
		TEXFLG_BILINEAR = 1,
	};
};

//==================================================================
class Sprite;

//==================================================================
///
//==================================================================
class SpriteManager
{
	static const int	SPRITES_PER_POOL = 32;

	TextureBase				*_texturep;
	bool					_own_texture;
	PSYSGFX::BasicBlend		_blendtype;
	int						_texflags;
	PArray<Sprite *>		_sprite_pools;
	int						_n_sprites;
	int						_max_w, _max_h;	// maximum dimensions that any item can take

public:
	SpriteManager();
	SpriteManager( SpriteManager *fromp );
	SpriteManager( PUtils::ImageBase *imgbasep );
	SpriteManager( const TCHAR *fnamep );

	~SpriteManager();

	Sprite	*AddSprite( int x, int y, int w, int h, int odx=0, int ody=0 ) throw(...);
	Sprite	*GetSprite( u_int idx );
	u_int	GetMaxSpriteWidth() const	{	return _max_w; }
	u_int	GetMaxSpriteHeight() const	{	return _max_h; }

	TextureBase	*GetTexture()
	{
		return _texturep;
	}

	void SetBasicBlend( PSYSGFX::BasicBlend blendtype )
	{
		_blendtype = blendtype;
	}

	void SetBilinear( bool onoff )
	{
		if ( onoff )
			_texflags |= SPRITE::TEXFLG_BILINEAR;
		else
			_texflags &= ~SPRITE::TEXFLG_BILINEAR;
	}

	PSYSGFX::BasicBlend	GetBasicBlend() const
	{
		return _blendtype;
	}

	void	BuildOneSprite( int odx=0, int ody=0 );
	void	BuildOneSpriteAlign( int align_x, int align_y );

	u_int	BuildSpritesFromSize( int itm_w, int itm_h,
		int offx, int offy,
		int odx, int ody,
		int max_ch_x, int max_ch_y,
		int max_tot, bool do_fit );
};

//==================================================================
///
//==================================================================
class Sprite
{
public:
	PSYSGFX::BasicBlend		_blendtype;
	int				_texflags;
	short			_u, _v;
	float			_s1, _t1, _s2, _t2;
	u_short			_w, _h;
	float 			_odx, _ody;

	class SpriteManager	*_originp;

	//==================================================================
	Sprite() :
		_blendtype(PSYSGFX::BASICBLEND_UNUSED),
		_texflags(SPRITE::TEXFLG_BILINEAR),
		_u(0), _v(0),
		_s1(0), _t1(0), _s2(0), _t2(0), 
		_w(0), _h(0), 
		_odx(0), _ody(0)
	{
	}

public:
	void SetDrawOffset( float odx, float ody )
	{
		_odx = odx;
		_ody = ody;
	}

	void SetBasicBlend( PSYSGFX::BasicBlend blendtype )
	{
		_blendtype = blendtype;
	}

	void SetBilinear( bool onoff )
	{
		if ( onoff )
			_texflags |= SPRITE::TEXFLG_BILINEAR;
		else
			_texflags &= ~SPRITE::TEXFLG_BILINEAR;
	}

	PSYSGFX::BasicBlend	GetBasicBlend() const
	{
		if ( _blendtype == PSYSGFX::BASICBLEND_UNUSED )
			return _originp->GetBasicBlend();
		else
			return _blendtype;
	}

	TextureBase	*GetTexture();

	friend class SpriteManager;
};

//==================================================================
inline TextureBase	*Sprite::GetTexture()
{
	return _originp->GetTexture();
}

//==================================================================
};

#endif